﻿using CatClient;
using PostSharp.Aspects;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

namespace PsCat.Aspet
{
    [Serializable]
    public abstract class CatBaseAttribute : OnMethodBoundaryAspect, ICatAttributeExtension
    {
        public Dictionary<int, object> IgnoreArgs
        {
            get;
            protected set;
        }

        public bool AsyncMethod
        {
            get;
            private set;
        }

        public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
        {
            if (method == null)
            {
                return;
            }
            this.ExtractIgnoreArgs(method);
            this.IsAsyncMethod(method);
            base.CompileTimeInitialize(method, aspectInfo);
        }

        private void ExtractIgnoreArgs(MethodBase method)
        {
            this.IgnoreArgs = new Dictionary<int, object>();
            ParameterInfo[] parameters = method.GetParameters();
            if (method.GetCustomAttributes(typeof(CatIgnoreAttribute), true).Length != 0)
            {
                for (int i = 0; i < parameters.Length; i++)
                {
                    this.IgnoreArgs.Add(i, null);
                }
                return;
            }
            for (int j = 0; j < parameters.Length; j++)
            {
                if (parameters[j].GetCustomAttributes(typeof(CatIgnoreAttribute), true).Length != 0)
                {
                    this.IgnoreArgs.Add(j, null);
                }
            }
        }

        private void IsAsyncMethod(MethodBase method)
        {
            AsyncStateMachineAttribute customAttribute = method.GetCustomAttribute<AsyncStateMachineAttribute>();
            bool flag = true;
            MethodInfo methodInfo = method as MethodInfo;
            if (methodInfo != null)
            {
                flag = typeof(Task).IsAssignableFrom(methodInfo.ReturnType);
            }
            if (customAttribute != null & flag)
            {
                this.AsyncMethod = true;
                return;
            }
            if (customAttribute != null)
            {
                string arg_5F_0 = "{0}.{1} with async syntax, but without task result.";
                Type expr_4D = method.DeclaringType;
                throw new FormatException(string.Format(arg_5F_0, (expr_4D != null) ? expr_4D.FullName : null, method.Name));
            }
            if (flag)
            {
                string arg_8A_0 = "{0}.{1} return task result, but without async syntax.";
                Type expr_78 = method.DeclaringType;
                throw new FormatException(string.Format(arg_8A_0, (expr_78 != null) ? expr_78.FullName : null, method.Name));
            }
            this.AsyncMethod = false;
        }
    }
}
